package cn.goktech.aop;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;

//使用注解定义当前类是个切面
//@Order(1)
//@Aspect
@Component
public class LogAspect {

    /*定义全局的切入点，被引用是直接使用方法名（）*/
   // @Pointcut("execution(* cn.goktech.aop.ComputerImp.*(..))")
    public void pintcut() {
    }
    /*execution表达式：语法：  execution(修饰符  返回值  包.类.方法名(参数) throws异常)
    *​	以execution(public *   cn.gok.service.UserServiceImpl.testService(..))  为例：
​        		   1、execution():   表达式主体，表达式需要写在（）中；
​               	2、第一个*号：   表示方法的返回的数据类型， *号表示所有的类型；
​               	3、cn.gok.service.UserServiceImpl：  表示全类名;
​				   4、testService():   对指定的方法进行增强操作;
​				   5、（..）: 示方法的参数，两个句点表示任何参数
    * */

    //五种通知类型：
    //前置：before
    //返回：AfterReturning
    //异常：AfterThrowing
    //后置：After
    //环绕：Around

    //通知通过切入点作用于连接点，切入点通过execution表达式来定义切入点
    //语法：  execution(修饰符  返回值  包.类.方法名(参数) throws异常)
    //JoinPoint连接点
   // @Before("pintcut()")
    public void before(JoinPoint point) {
        System.out.println("【前置通知】。。。方法：" + point.getSignature().getName() + ",参数=" + Arrays.toString(point.getArgs()));
    }

    //returning=“参数值”  一定要在方法的参数列表中
   // @AfterReturning(value = "pintcut()", returning = "result")
    public void afterReturning(JoinPoint point, Object result) {
        System.out.println("【返回通知】。。。方法：" + point.getSignature().getName() + ",参数=" + Arrays.toString(point.getArgs()) + "result=" + result);
    }

  //  @AfterThrowing(value = "pintcut()", throwing = "e")
    public void afterThrowing(JoinPoint point, Exception e) {
        System.out.println("【异常通知】。。。方法：" + point.getSignature().getName() + ",参数=" + Arrays.toString(point.getArgs()) + "e=" + e);
    }

    //@After(value = "pintcut()")
    public void after(JoinPoint point) {
        System.out.println("【后置通知】。。。方法：" + point.getSignature().getName() + ",参数=" + Arrays.toString(point.getArgs()));
    }

   // @Around(value = "pintcut()")
    public void around(ProceedingJoinPoint point) {
        Object result = null;
        try {
            System.out.println("环绕前置通知");
            result = point.proceed();
            System.out.println("环绕返回通知");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("环绕异常通知");
        } finally {
            System.out.println("环绕后置通知");
        }

    }

}
